package ch.fusun.baron.basic.turntask;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import ch.fusun.baron.core.injection.Inject;
import ch.fusun.baron.player.Dynasty;
import ch.fusun.baron.player.Gender;
import ch.fusun.baron.player.Player;
import ch.fusun.baron.player.api.Country;
import ch.fusun.baron.player.api.MarriageService;
import ch.fusun.baron.property.api.PropertyService;
import ch.fusun.baron.turn.TurnTask;

/**
 * Redistributes countries if a member of a {@link Dynasty} died.
 */
public class HeritageTurnTask implements TurnTask {

	@Inject
	private transient PropertyService propertyService;

	@Inject
	private transient MarriageService marriageService;

	/**
	 * Kryo
	 */
	public HeritageTurnTask() {
		// Kryo
	}

	@Override
	public void execute() {
		Map<Player, List<Country>> countries = propertyService
				.getAllOwnerships(Player.class, Country.class);
		for (Entry<Player, List<Country>> entry : countries.entrySet()) {
			Player defunct = entry.getKey();
			if (defunct.isDead()) {
				for (Country country : countries.get(defunct)) {
					Player heir = findHeir(defunct);
					if (heir == null) {
						Player spouse = marriageService.getSpouse(defunct);
						if (spouse != null) {
							heir = findHeir(spouse);
						}
					}
					propertyService.setOwnership(heir, country);
				}
			}
		}
	}

	private Player findHeir(Player player) { // SDZ move to
												// PlayerService
		if (!player.isDead()) {
			return player;
		}
		Player heir = findHeirInDescendants(player);
		if (heir != null) {
			return heir;
		}

		Player father = player.getFather();
		if (father != null) {
			return findHeir(father);
		}

		return null;
	}

	private Player findHeirInDescendants(Player defunct) {
		sort(defunct.getChildren());
		for (Player child : defunct.getChildren()) {
			if (!child.isDead()) {
				return child;
			}
		}
		// No child alive, search in nephews
		for (Player child : defunct.getChildren()) {
			Player possibleHeir = findHeirInDescendants(child);
			if (possibleHeir != null) {
				return possibleHeir;
			}
		}
		// No descendants
		return null;
	}

	private static void sort(List<Player> children) {
		Collections.sort(children, new Comparator<Player>() {

			@Override
			public int compare(Player player1, Player player2) {
				if (!player1.getGender().equals(player2.getGender()))

				{
					return player1.getGender().equals(Gender.MALE) ? 1 : -1;
				}
				return (player1.getAge() > (player2.getAge())) ? -1 : 1;
			}
		});
	}
}
